﻿using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace SystemFrameWork
{
    public class Encrypt
    {
        #region symmetric encrypt/decrypt

        /// <summary>
        /// The base class from which all implementations of symmetric
        /// </summary>
        private SymmetricAlgorithm mobjCryptoService;

        /// <summary>
        /// the key for encryption
        /// </summary>
        private string key;

        /// <summary>
        /// Constructor
        /// </summary>
        public Encrypt()
        {
            this.mobjCryptoService = new RijndaelManaged();
            this.key = "Guz(%&hj7x89H$yuBI0456FtmaT5&fvHUFCy76*h%(HilJ$lhj!y6&(*jkP87jH7";
        }

        /// <summary>
        /// get the encryption key
        /// </summary>
        /// <returns>Encryption Key</returns>
        private byte[] GetLegalKey()
        {
            string temp = this.key;
            this.mobjCryptoService.GenerateKey();
            byte[] bytTemp = this.mobjCryptoService.Key;
            int keyLength = bytTemp.Length;

            if (temp.Length > keyLength)
            {
                temp = temp.Substring(0, keyLength);
            }
            else if (temp.Length < keyLength)
            {
                temp = temp.PadRight(keyLength, ' ');
            }

            return ASCIIEncoding.ASCII.GetBytes(temp);
        }

        /// <summary>
        /// Get the initial vector: IV
        /// </summary>
        /// <returns>the initial vector: IV</returns>
        private byte[] GetLegalIV()
        {
            string temp = "E4ghj*Ghg7!rNIfb&95GUY86GfghUb#er57HBh(u%g6HJ($jhWk7&!hg4ui%$hjk";
            this.mobjCryptoService.GenerateIV();
            byte[] bytTemp = this.mobjCryptoService.IV;
            int ivLength = bytTemp.Length;

            if (temp.Length > ivLength)
            {
                temp = temp.Substring(0, ivLength);
            }
            else if (temp.Length < ivLength)
            {
                temp = temp.PadRight(ivLength, ' ');
            }

            return ASCIIEncoding.ASCII.GetBytes(temp);
        }

        /// <summary>
        /// encrypt method
        /// </summary>
        /// <param name="source">the string will be encrypted</param>
        /// <returns>the encrypted string</returns>
        public string Encrypto(string source)
        {
            byte[] bytIn = UTF8Encoding.UTF8.GetBytes(source);
            MemoryStream ms = new MemoryStream();
            this.mobjCryptoService.Key = this.GetLegalKey();
            this.mobjCryptoService.IV = this.GetLegalIV();
            ICryptoTransform encrypto = this.mobjCryptoService.CreateEncryptor();
            CryptoStream cs = new CryptoStream(ms, encrypto, CryptoStreamMode.Write);
            cs.Write(bytIn, 0, bytIn.Length);
            cs.FlushFinalBlock();
            ms.Close();
            byte[] bytOut = ms.ToArray();

            return Convert.ToBase64String(bytOut);
        }

        /// <summary>
        /// decrypt method
        /// </summary>
        /// <param name="source">the string is about to decrypt</param>
        /// <returns>the decrypted string</returns>
        public string Decrypto(string source)
        {
            byte[] bytIn = Convert.FromBase64String(source);
            MemoryStream ms = new MemoryStream(bytIn, 0, bytIn.Length);
            this.mobjCryptoService.Key = this.GetLegalKey();
            this.mobjCryptoService.IV = this.GetLegalIV();
            ICryptoTransform encrypto = this.mobjCryptoService.CreateDecryptor();
            CryptoStream cs = new CryptoStream(ms, encrypto, CryptoStreamMode.Read);
            StreamReader sr = new StreamReader(cs);

            return sr.ReadToEnd();
        }

        #endregion
    }
}
